package com.turing.post.thirdinterface.impl;

import java.io.Reader;
import java.io.StringReader;
import java.math.BigInteger;
import java.nio.charset.Charset;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

import com.turing.post.thirdinterface.util.ThirdInterfaceRespCode;
import com.turing.post.util.HexDump;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;

/**
 * XML报文解析辅助类
 * @author ZXL
 *
 */
public final class PSBCBankXmlHelper {
	/**
	 * XML编码GBK
	 */
	public static final String XML_CHARSET_GBK = "GBK";
	/**
	 * XML编码UTF-8
	 */
	public static final String XML_CHARSET_UTF = "UTF-8";
	/**
	 * 消息头
	 */
	public static final String XML_XYJ = "XYJ";
	/**
	 * 结束标志
	 */
	public static final String XML_END = "***";
	/**
	 * 处理成功
	 */
	public static final String XML_SUCCESS = "0000";
	/**
	 * 卡/帐户号码
	 */
	public static final String XML_ACC = "01";
	/**
	 * 证件类型
	 */
	public static final String XML_IDTYPE = "01";
 	/**
	 * 开卡
	 */
	public static final String XML_OPENCARD = "XYJ01";
	/**
	 * 销户
	 */
	public static final String XML_CANCELCARD = "XYJ02";
	/**
	 * 充值
	 */
	public static final String XML_DEPOSIT = "XYJ03";
	/**
	 * 赎回
	 */
	public static final String XML_REDEMP = "XYJ04";
	/**
	 * 对明细账
	 */
	public static final String XML_RECONCILIATIONDETAIL = "XYJ05";
	/**
	 * 对总账
	 */
	public static final String XML_RECONCILIATIONTOTAL = "XYJ06";
	
	/**
	 * 校正交易
	 */
	public static final String XML_ADJUSTBUSINESS = "XYJ07";
	
	/**
	 * XML主节点
	 */
	public static final String XML_NODE_BANKINTF = "BANKINTF";
	/**
	 * XML公共节点
	 */
	public static final String XML_NODE_PUB = "PUB";
	/**
	 * XML输入节点
	 */
	public static final String XML_NODE_IN = "IN";
	/**
	 * XML输出节点
	 */
	public static final String XML_NODE_OUT = "OUT";
	
	/**
	 * XML交易码
	 */
	public static final String XML_NODE_TRADEID = "TRADE_ID";
	/**
	 * XML发起交易的具体人或设备
	 */
	public static final String XML_NODE_TELLER = "TELLER";
	/**
	 * XML委托代码
	 */
	public static final String XML_NODE_ENTERPRISE = "ENTERPRISE";
	
	/**
	 * XML主账号
	 */
	public static final String XML_NODE_CUSTID = "CUST_ID";
	/**
	 * XML特殊卡类型
	 */
	public static final String XML_NODE_DPTID = "DPT_ID";
	/**
	 * XML客户姓名
	 */
	public static final String XML_NODE_CUSTNAME = "CUST_NAME";
	/**
	 * XML身份证号
	 */
	public static final String XML_NODE_PASSID = "PASS_ID";
	/**
	 * XML证件类型
	 */
	public static final String XML_NODE_PAYERTYPE = "PAYER_TYPE";
	/**
	 * XML卡/帐户类型
	 */
	public static final String XML_NODE_ACCTYPE = "ACC_TYPE";
	/**
	 * XML卡/帐户号码
	 */
	public static final String XML_NODE_ACC = "ACC";
	/**
	 * XML交易流水号
	 */
	public static final String XML_NODE_TRADESEQ = "TRADE_SEQ";
	/**
	 * XML支付(扣款)(退款)金额
	 */
	public static final String XML_NODE_MONEYTRADE = "MONEY_TRADE";
	/**
	 * XML日期
	 */
	public static final String XML_NODE_TRADEDATE = "TRADE_DATE";
	/**
	 * XML对账文件名
	 */
	public static final String XML_NODE_FILENAME = "FILE_NAME";
	
	/**
	 * XML交易返回码
	 */
	public static final String XML_NODE_RETCODE = "RET_CODE";
	/**
	 * XML中文信息
	 */
	public static final String XML_NODE_MSG = "MSG";
	/**
	 * XML银行流水号
	 */
	public static final String XML_NODE_BANKSEQ = "BANK_SEQ";
	/**
	 * XML交易完成时间
	 */
	public static final String XML_NODE_RETTIME = "RET_TIME";
	
	/**
	 * XML原交易流水号
	 */
	public static final String XML_TRADE_SEQ_ORG = "TRADE_SEQ_ORG";
	
	/**
	 * XML原交易码
	 */
	public static final String XML_TRADE_ID_ORG = "TRADE_ID_ORG";
	
	/**
	 * XML原交易日期
	 */
	public static final String XML_TRADE_DATE_ORG = "TRADE_DATE_ORG";
	
	/**
	 * XML原交易返回码
	 */
	public static final String XML_RET_CODE_ORG = "RET_CODE_ORG";
	
	/**
	 * XML原中文信息
	 */
	public static final String XML_MSG_ORG = "MSG_ORG";
	
	/**
	 * XML原银行流水号
	 */
	public static final String XML_BANK_SEQ_ORG = "BANK_SEQ_ORG";
	
	/**
	 * XML原交易完成时间
	 */
	public static final String XML_RET_TIME_ORG = "RET_TIME_ORG";
	
	/**
	 * XML订单号
	 */
	public static final String XML_CO_NUM = "CO_NUM";

	/**
	 * 根据字节数组,返回org.jdom2.Document
	 * 
	 * @param ibuf
	 * @return
	 * @throws Exception
	 */
	public static Document getXmlDocumentFromBuffer(byte[] ibuf)
			throws PCPSApplicationException {
		try {
			PCPSUtil.Log(HexDump.EOL + "PCPS request data LEN " + ibuf.length
					+ HexDump.EOL + HexDump.dump(ibuf, 0, 0));
			SAXBuilder builder = new SAXBuilder();
			String reqXml = new String(ibuf, Charset.forName(XML_CHARSET_GBK))
					.trim();
			Reader in = new StringReader(reqXml);
			return builder.build(in);
		} catch (Exception ex) {
			PCPSUtil.Log("getXmlDocumentFromBuffer error!", ex);
			throw new PCPSApplicationException(ThirdInterfaceRespCode.RC_PARAMETER, 
					"getXmlDocumentFromBuffer error!");
		}
	}

	/**
	 * 增加字符串
	 * 
	 * @param parent
	 * @param nodeName
	 * @param nodeValue
	 */
	public static void addStringElement(Element parent, String nodeName,
			String nodeValue) {
		if (PCPSUtil.isEmpty(nodeValue))
			return;
		Element el = new Element(nodeName);
		el.addContent(nodeValue);
		parent.addContent(el);
	}

	/**
	 * 返回必须存在的字符串
	 * 
	 * @param root
	 * @param nodeName
	 * @return
	 * @throws Exception
	 */
	public static String getMandatoryString(Element root, String nodeName)
			throws PCPSApplicationException {
		Element node = root.getChild(nodeName);
		if (node == null)
			throw new PCPSApplicationException(ThirdInterfaceRespCode.RC_PARAMETER, 
					nodeName + " 不存在!");
		String nodeval = node.getTextTrim();
		if (PCPSUtil.isEmpty(nodeval))
			throw new PCPSApplicationException(ThirdInterfaceRespCode.RC_PARAMETER, 
					nodeName + " 为NULL!");
		return nodeval;
	}

	/**
	 * 获取可选字符串
	 * 
	 * @param root
	 * @param nodeName
	 * @return
	 */
	public static String getOptionalString(Element root, String nodeName) {
		Element node = root.getChild(nodeName);
		return (node != null) ? node.getTextTrim() : "";
	}

	/**
	 * 解析数字
	 * 
	 * @param root
	 * @param nodeName
	 * @return
	 * @throws Exception
	 */
	public static BigInteger getInteger(Element root, String nodeName)
			throws PCPSApplicationException {
		String str = getMandatoryString(root, nodeName);
		BigInteger ival = BigInteger.ZERO;

		try {
			ival = new BigInteger(str);
		} catch (Exception e) {
			throw new PCPSApplicationException(ThirdInterfaceRespCode.RC_PARAMETER, 
					nodeName + " 数字非法!");
		}

		return ival;
	}
}
